﻿using DrawIO45.Draws.Business;
using DrawIO45.Models.DrawIOs;
using DrawIO45.Models.Logic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace DrawIO45.Draws
{
    public static class DrawHelper
    {
        public const int ItemCellHeight = 26;

        public static string GetRandomId(int count = 22)
        {
            return Guid.NewGuid().ToString("N").Substring(count);
        }

        public static bool CanFindCellById(Root root, string id)
        {
            return root.MxCells.Any(n => string.Equals(n.Id, id, StringComparison.OrdinalIgnoreCase));
        }

        public static bool CanFindCellByLClass(Root root, LClassInfo classInfo)
        {
            return CanFindCellById(root, classInfo.Id);
        }

        public static bool CanFindCellByLClass(Root root, List<LClassInfo> classInfos, Type type)
        {
            var classInfo = classInfos.FirstOrDefault(n => n.Source == type);
            if (classInfo == null)
                return false;

            return CanFindCellById(root, classInfo.Id);
        }

        public static bool CanFindCellByLClass(Root root, List<DILocationInfo<LClassInfo>> classInfos, Type type)
        {
            var classInfo = classInfos.FirstOrDefault(n => n.Object.Source == type);
            if (classInfo == null)
                return false;

            return CanFindCellById(root, classInfo.Object.Id);
        }

        static DISize GetSize(LClassInfo classInfo)
        {
            var texts = new List<string>();
            texts.Add(classInfo.Name);

            var methodInfos = classInfo.MethodInfos;

            foreach (var item in methodInfos ?? new List<LMethodInfo>())
            {
                texts.Add(item.GetFormatName());
            }

            var properties = classInfo.Properties;
            foreach (var item in properties ?? new List<LPropertyInfo>())
            {
                texts.Add(item.GetFormatName());
            }

            var width = texts.Max(n => n.Length) * 7;
            var height = texts.Count * ItemCellHeight + 8;

            return new DISize
            {
                Height = height,
                Width = width,
            };
        }

        public static MXFile DrawFile(List<LClassInfo> allClassInfo, params IDrawOnRoot[] draws)
        {
            var maxWitdth = 1600;

            var func = GetPlacingRobotFunc(maxWitdth, new DISize(10, 10));

            var classInfos = new List<DILocationInfo<LClassInfo>>();
            foreach (var item in allClassInfo)
            {
                var size = GetSize(item);

                // 将对应的内容挨个排下来
                var np = func.Invoke(size);
                classInfos.Add(new DILocationInfo<LClassInfo>(np, size, item));
            }

            if (classInfos?.Any() != true)
                return null;

            var model = new MxGraphModel
            {
                Root = new Root(),
            };

            MXFile mxFile = new MXFile
            {
                Diagram = new List<Diagram>
                {
                    new Diagram
                    {
                        Id = GetRandomId(),
                        Name = "Page-1",
                        MxGraphModel = model,
                    },
                }
            };

            var root = model.Root;

            root.MxCells.Add(new MxCell { Id = "0" });
            root.MxCells.Add(new MxCell { Id = "1", Parent = "0" });

            DrawClassToRoot(classInfos, root);

            // 挨个绘画内容
            if (draws?.Any() == true)
            {
                foreach (var itemDraw in draws)
                {
                    try
                    {
                        itemDraw.DrawOnRoot(root, classInfos);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"尝试进行绘画时出错了:{itemDraw.GetType().FullName}", ex);
                    }
                }
            }

            return mxFile;
        }

        private static void DrawClassToRoot(List<DILocationInfo<LClassInfo>> classInfos, Root root)
        {
        }


        public static Func<DISize, DIPoint> GetPlacingRobotFunc(int maxWidth, DISize interval)
        {
            int cursorX = 0;
            int cursorY = 0;

            int maxHeight = 0;

            return input =>
            {
                var np = new DIPoint
                {
                    X = cursorX,
                    Y = cursorY,
                };

                cursorX += interval.Width + input.Width;

                var newY = cursorY + interval.Height + input.Height;
                if (newY > maxHeight)
                    maxHeight = newY;

                if (cursorX > maxWidth)
                {
                    cursorX = 0;
                    cursorY = maxHeight;
                }

                return np;
            };
        }
    }
}
